import { connect } from 'dva';
import * as THREE from 'three'
import { useEffect, useRef } from 'react';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'

 const BufferGeometryPage = (props) => {
   const sceneRef = useRef(null)
   const cameraRef = useRef(null)
   const rendererRef = useRef(null)
   const guiRef = useRef(null)
   const width = 1000; //宽度
   const height = 800; //高度
   useEffect(()=>{
    init()
   }, [])
   const init = () => {
      // 0.添加GUI
      const eventObj = {
        Fullscreen: function(){
         document.body.requestFullscreen()
        },
        Exitscreen: () => {
          document.exitFullscreen()
        }
      }
      guiRef.current = new GUI()
      guiRef.current.add(eventObj, "Fullscreen").name('全屏')
      guiRef.current.add(eventObj, "Exitscreen").name('退出全屏')

      // 1.创建3D场景对象Scene
      sceneRef.current = new THREE.Scene();

      // 4.创建一个长方体几何对象Geometry
      setGeometry()

      // 2. 定义虚拟相机部分
      setCamera()

      // 5. 坐标辅助器
      const axesHelper = new THREE.AxesHelper(500)
      sceneRef.current.add(axesHelper)

      // 3.渲染器
      setRenderer()

      // 全屏 rendererRef.current.domElement.requestFullscreen()
      window.addEventListener("resize",()=>{
        rendererRef.current.setSize(window.innerWidth,window.innerHeight);
        cameraRef.current.aspect = window.innerWidth/window.innerHeight;
        cameraRef.current.updateProjectionMatrix()
      })

   }
   // 创建相机
   const setCamera = () => {
      // width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
      cameraRef.current = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
      // 实例化一个透视投影相机对象
      // 根据需要设置相机位置具体值
      cameraRef.current.position.set(25, 25, 25);
      cameraRef.current.lookAt(0,5,0);//指向mesh对应的位置
   }
   // 创建三角形、矩形 平面
   const setGeometry = () => {
     // example 1: 点，索引画图
     getGeometryByIndex()
     // example 2:六面不同材质的立方体
     getBoxGeometry();
     // example 3:圆形-扇形
     getCircleGeometry();
     // example 4:圆锥
     getConeGeometry() 
     // example 5:圆柱
     getCylinderGeometry()
   }
   // 创建渲染器
   const setRenderer = () => {
      // 创建渲染器对象
      rendererRef.current = new THREE.WebGLRenderer();
      rendererRef.current.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
      rendererRef.current.render(sceneRef.current, cameraRef.current); //执行渲染操作
      document.getElementById('webgl').appendChild(rendererRef.current.domElement);
      // 6. 轨道控制器
      const controls = new OrbitControls(cameraRef.current, rendererRef.current.domElement)

      function animate(){
        requestAnimationFrame(animate)
        controls.update() 
        // mesh.rotation.x += 0.01;
        // mesh.rotation.y += 0.01;
        rendererRef.current.render(sceneRef.current, cameraRef.current)
      }
      animate()
   }
   // 用点，索引 画面图
   const getGeometryByIndex = () => {
      const geometry = new THREE.BufferGeometry()
      //创建三个点，每个点三维，所以每个点3个坐标位移数
      // const vertices = new Float32Array([-1.0,-1.0,0.0,  1.0, -1.0,0.0, 1.0, 1.0, 0.0, 
      //   -1.0,-1.0,0.0, 1.0,1.0,0.0, -1.0,1.0,0.0
      // ])
      const vertices = new Float32Array([-1.0,-1.0,0.0,  1.0, -1.0,0.0, 1.0, 1.0, 0.0, 
        -1.0,1.0,0.0
      ])
      // 创建顶点属性
      geometry.setAttribute('position',new THREE.BufferAttribute(vertices, 3));
      const indices = new Uint16Array([0,1,2,2,3,0]) 
      geometry.setIndex(new THREE.BufferAttribute(indices, 1))
      const material0 = new THREE.MeshBasicMaterial({
        color: 0x00ff00,
        side: THREE.DoubleSide,
      });
      const material1 = new THREE.MeshBasicMaterial({
        color: 0x3300ff,
        side: THREE.DoubleSide,
      }); 
    /**
      * 设置两个顶点组，形成2个材质
    * params1: 起始索引
    * params2: 设置的顶点数量
    * params3: 用哪个索引的材质
    * 从索引0开始，3个顶点用第一个材质
    */
      geometry.addGroup(0,3,0)
      geometry.addGroup(3,3,1)
      const mesh = new THREE.Mesh(geometry, [material0, material1]); //网格模型对象Mesh
      sceneRef.current.add(mesh);
   }
   // 六面不同材质的立方体
   const getBoxGeometry = () => {
      const geometry2 = new THREE.BoxGeometry(1, 1, 1,3); 
      //创建一个材质对象Material
      const cubematerial1 = new THREE.MeshBasicMaterial({
        color: 0xff0000,
        wireframe: true
      }); 
      const cubematerial2 = new THREE.MeshBasicMaterial({
        color: 0xaeff00,
      }); 
      const cubematerial3 = new THREE.MeshBasicMaterial({
        color: 0xffae00,
      }); 
      const cubematerial4 = new THREE.MeshBasicMaterial({
        color: 0xff0088,
      }); 
      const cubematerial5 = new THREE.MeshBasicMaterial({
        color: 0x8131e3,
      }); 
      const cubematerial6 = new THREE.MeshBasicMaterial({
        color: 0x31e3b6,
      }); 
      const mesh2 = new THREE.Mesh(geometry2, [cubematerial1,cubematerial2,cubematerial3,cubematerial4,cubematerial5,cubematerial6]); //网格模型对象Mesh
      mesh2.geometry.scale(1,1,-1)
      // 设置网格模型在三维空间中的位置坐标，默认是坐标原点
      mesh2.position.set(5,0,0);
      sceneRef.current.add(mesh2);
      // 1. test边缘几何体
      // 2. 创建其边缘几何体
      let edgeGeometry = new THREE.EdgesGeometry(geometry2);
      // 3. 创建线段材质 LineBasicMaterial
      const material2 = new THREE.LineBasicMaterial({
        color: 0xffffff,
        linewidth: 1,
        // linecap: 'round',
        // linejoin: 'round'
      })
      // 4. 创建线段 LineSegments
      let edges = new THREE.LineSegments(edgeGeometry, material2);
      // 有矩阵属性的只有Mesh类，边缘几何体是由几何体创建(Geometry类),更新世界矩阵需要更新mesh类的
      mesh2.updateWorldMatrix(true,true)
      edges.matrix.copy(mesh2.matrixWorld);
      edges.matrix.decompose(edges.position,edges.quaternion,edges.scale)
      sceneRef.current.add(edges)
   }
   // 圆形-扇形
   const getCircleGeometry = () => {
      const circlegeometry = new THREE.CircleGeometry(3, 34, 0, 1/4 * Math.PI)
      const circlemetrial = new THREE.MeshBasicMaterial({ color: 0x31e3b6, })
      const circlemesh = new THREE.Mesh(circlegeometry, circlemetrial); //网格模型对象Mesh
      sceneRef.current.add(circlemesh); 
   }
   // 圆锥体
   const getConeGeometry = () => {
      const geometry = new THREE.ConeGeometry(1,4,32,1,true,30, Math.PI)
      const metrial = new THREE.MeshBasicMaterial({color: 0xffff00})
      const cone = new THREE.Mesh(geometry,metrial)
      cone.position.set(10,10,10);
      sceneRef.current.add(cone);
   }
  // 圆柱
  const getCylinderGeometry = () => {
    const geometry = new THREE.CylinderGeometry(1,2,3,32)
    const metrial = new THREE.MeshBasicMaterial({color: 0xaeff00})
    const cone = new THREE.Mesh(geometry,metrial)
    cone.position.set(-5,10,10);
    sceneRef.current.add(cone);
  }

  return (
    <div>
      <h1>几何体基类：BufferGeometry</h1>
      <div id="webgl" style={{marginTop: 10,marginLeft: 10}}></div>
    </div>
  );
}
export default connect(({common})=>({
  userInfo: common.userInfo,
}))(BufferGeometryPage)